雖然從Elasticsearch拿到資料,但是裡面充滿了各種未處理的資料,該進行資料科學的第二步驟-前處理(Preproccessing),這部分就用Pandas來做前處理。
提到資料科學、ML、DL就會聯想到的好工具-Pandas,Pandas本身支援從JSON、CSV、EXCEL等常見的檔案讀取,也支援從資料庫把資料讀取出來,最重要的是能夠快速整理與篩選資料,真的是前處理時最好的幫手!!Anaconda不用額外再安裝Pandas,預設就安裝在裡面,就不介紹安裝方法了,基本的使用方法請參考官網(官網的教學算是少數寫的還算詳細的,與Tensorflow比起來算是很詳細XD)。
接續上一篇文章取得的res
,用Pandaax來把資料快速整理成理想的形式,首先要了解res
裡面包含的內容,然後從中取出要前處理的內容,關於res
內包含的格式與項目就不在這邊贅述,直接就把Event Log相關資料取出:
import pandas as pd
dataframe = pd.DataFrame([i['_source'] for i in res['hits']['hits']])
print(dataframe.columns)
# ['@timestamp', 'beat', 'computer_name', 'event_data', 'event_id', 'host',
# 'level', 'log_name', 'process_id', 'provider_guid', 'record_number',
# 'source_name', 'tags', 'thread_id', 'type', 'user', 'version']
除了@timestamp
欄位的資料是Numerical Data,其他都算是Categorical Data,接下來就先了解其他各項各自有多少unique的內容,可惜的是,pd.unique(values)
只能處理1維的values,因此只能一項一項來列出,詳細內容我就不列出了,只列出有助於後續處理的資訊:
for i in dataframe.columns.tolist():
try:
print(pd.unique(dataframe[i]))
except Exception as e:
print(e) # unhashable type: 'dict' beat, unhashable type: 'dict' event_data, unhashable type: 'dict' host, unhashable type: 'list' tags, unhashable type: 'dict' user
從上段程式碼執行結果可以看到幾個unhashable type: 'list'
、unhashable type: 'dict'
,先對unhashable type: 'dict'
來點前處理,讓dataframe
變得更平面一點:
for i in dataframe.columns.tolist():
try:
if isinstance(dataframe[i].iloc[0], dict):
for key in dataframe[i].iloc[0].keys():
dataframe[i + '_' + key] = dataframe[i].apply(lambda x:x[key])
else:
print(pd.unique(dataframe[i]))
except Exception as e:
print(e, i) # unhashable type: 'list' tags, 'SourceIp' event_data
print(dataframe.columns)
#Index(['@timestamp', 'beat', 'computer_name', 'event_data', 'event_id', 'host',
# 'level', 'log_name', 'process_id', 'provider_guid', 'record_number',
# 'source_name', 'tags', 'thread_id', 'type', 'user', 'version',
# 'beat_name', 'beat_domain', 'beat_type', 'beat_identifier',
# 'event_data_name', 'event_data_domain', 'event_data_type',
# 'event_data_identifier', 'host_name', 'host_domain', 'host_type',
# 'host_identifier', 'user_name', 'user_domain', 'user_type',
# 'user_identifier'],
# dtype='object')
unhashable type: 'list' tags
依個人需求決定要不要處理,因為(dataframe['tags'].apply(lambda x:len(x)) > 1).any() # False
沒有長度大於0的List,就先依照以下處理,為了之後還能夠檢查dataframe['tags']
,這邊就命名成其他欄位(tags_
):
dataframe['tags_'] = dataframe['tags'].apply(lambda x:x[0])
'SourceIp' event_data
是因為dataframe['event_data']
的dict
沒有統一的Key,這部分要另外處裡:
s = set()
for i in range(len(dataframe['event_data'])):
for j in list(dataframe['event_data'].iloc[i].keys()):
s.add(j)
for i in s:
dataframe['event_data_' + i] = None
for i in range(len(dataframe['event_data'])):
for key in dataframe['event_data'].iloc[i].keys():
dataframe['event_data_' + key].iloc[i] = dataframe['event_data'].iloc[i][key]